home *** CD-ROM | disk | FTP | other *** search
/ Aminet 39 / Aminet 39 (2000)(Schatztruhe)[!][Oct 2000].iso / Aminet / game / shoot / Orbit_src.lha / Orbit / source / planet.c < prev    next >
Encoding:
C/C++ Source or Header  |  2000-07-04  |  23.9 KB  |  980 lines

  1. /*
  2.     Amiga port by Oliver Gantert
  3.  
  4.     27.04.2000 - fixed some compiler warnings
  5.     21.06.2000 - some glColor3d() changed to glColor3f()
  6. */
  7. /*
  8.  
  9. ORBIT, a freeware space combat simulator
  10. Copyright (C) 1999  Steve Belczyk <steve1@genesis.nred.ma.us>
  11.  
  12. This program is free software; you can redistribute it and/or
  13. modify it under the terms of the GNU General Public License
  14. as published by the Free Software Foundation; either version 2
  15. of the License, or (at your option) any later version.
  16.  
  17. This program is distributed in the hope that it will be useful,
  18. but WITHOUT ANY WARRANTY; without even the implied warranty of
  19. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  20. GNU General Public License for more details.
  21.  
  22. You should have received a copy of the GNU General Public License
  23. along with this program; if not, write to the Free Software
  24. Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  25.  
  26. */
  27.  
  28. #include "orbit.h"
  29.  
  30. static float MaterialColor[] = {
  31.   1.0, 1.0, 1.0, 1.0}
  32. static float specular[] = {
  33.   0.0, 0.0, 0.0, 1.0}
  34. static float emission[] = {
  35.   0.0, 0.0, 0.0, 1.0}
  36. ;
  37.  
  38. void DrawPlanets()
  39. /*
  40.  *  Draw all the planets
  41.  */
  42. {
  43.   int p;
  44.  
  45.   /* Draw orbits */ 
  46.   if (draw_orbits) DrawOrbits(); 
  47.   
  48.   for (p=0; p<NPLANETS; p++)
  49.   {
  50.     if (!planet[p].hidden) DrawPlanet (p);
  51.   }
  52. }
  53.  
  54. void DrawPlanet (int p)
  55. /*
  56.  *  Draw the pretty planet
  57.  */
  58. {
  59.   double th, r2, v[3];
  60.   int pr;
  61.  
  62.   /* Set color to white, will be modulated with texture */
  63.   if (textures)
  64.   {
  65.     glMaterialfv (GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialColor);
  66.     glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT, MaterialColor);
  67.   }
  68.   else
  69.   {
  70.     glMaterialfv (GL_FRONT_AND_BACK, GL_DIFFUSE, planet[p].color);
  71.     glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT, planet[p].color);
  72.   }
  73.   
  74.   glMaterialfv (GL_FRONT_AND_BACK, GL_SPECULAR, specular); 
  75.   glMaterialfv (GL_FRONT_AND_BACK, GL_EMISSION, emission); 
  76.   glMaterialf  (GL_FRONT_AND_BACK, GL_SHININESS, 0.0); 
  77.  
  78.   glPushMatrix();
  79.  
  80.   /* How far away from view is this planet? */
  81.   Vsub (v, planet[p].pos, player.pos);
  82.   planet[p].absrange2 = Mag2(v);
  83.   planet[p].range2 = r2 = planet[p].absrange2 / planet[p].radius2;
  84.  
  85.   /* Translate to where the planet is */
  86.   Vsub (v, planet[p].pos, player.pos);
  87.   glTranslated (v[0], v[1], v[2]);
  88.   th = fmod (absT, 120.0);
  89.   th = 360.0*th / 120.0;
  90.  
  91.   /* Don't bother with oblicity or rotation if it's just a point */
  92.   if (r2 < 200.0*200.0)
  93.   {
  94.     /* Planet oblicity */
  95.     glRotated (planet[p].oblicity, 1.0, 0.0, 0.0);
  96.  
  97.     /* Moons get their primary's oblicity as well */
  98.     if (planet[p].is_moon)
  99.     {
  100.       pr = planet[p].primary;
  101.       glRotated (planet[pr].oblicity, 1.0, 0.0, 0.0);
  102.     }
  103.   }
  104.  
  105.   glPushMatrix();  /* Save un-rotated matrix */
  106.  
  107.   /* Planet rotation */
  108.   if (r2 < 200.0*200.0) glRotated (th, 0.0, 0.0, 1.0);
  109.  
  110.   if (r2 < 5.0 * 5.0)
  111.   {
  112.     if (textures) glEnable (GL_TEXTURE_2D);
  113.     glBindTexture (GL_TEXTURE_2D, planet[p].texid);
  114.     glCallList (planet[p].list320);
  115.   }
  116.   else if (r2 < 25.0 * 25.0)
  117.   {
  118.     if (textures) glEnable (GL_TEXTURE_2D);
  119.     glBindTexture (GL_TEXTURE_2D, planet[p].texid);
  120.     glCallList (planet[p].list80);
  121.   }
  122.   else if (r2 < 200.0 * 200.0)
  123.   {
  124.     if (textures) glEnable (GL_TEXTURE_2D);
  125.     glBindTexture (GL_TEXTURE_2D, planet[p].texid);
  126.     glCallList (planet[p].list20);
  127.   }
  128.   else if (r2 < (5000.0 * 5000.0))
  129.   {
  130.     glDisable (GL_TEXTURE_2D);
  131.     glDisable (GL_LIGHTING);
  132.     glPointSize (2.0);
  133.     glBegin (GL_POINTS);
  134.     glColor3fv (planet[p].color);
  135.     glVertex3d (0.0, 0.0, 0.0);
  136.     glEnd();
  137.   }
  138.   else if (r2 < (50000.0 * 50000.0))
  139.   {
  140.     glDisable (GL_TEXTURE_2D);
  141.     glDisable (GL_LIGHTING);
  142.     glPointSize (1.0);
  143.     glBegin (GL_POINTS);
  144.     glColor3fv (planet[p].color);
  145.     glVertex3d (0.0, 0.0, 0.0);
  146.     glEnd();
  147.   }
  148.  
  149.   glDisable (GL_TEXTURE_2D);
  150.   glEnable (GL_LIGHTING);
  151.  
  152.   /* Pop rotate matrix */
  153.   glPopMatrix();
  154.  
  155.   glPopMatrix();
  156. }
  157.  
  158. void MakePlanetLists()
  159. /*
  160.  *  Define planet display lists
  161.  */
  162. {
  163.   int p;
  164.  
  165.   for (p=0; p<NPLANETS; p++)
  166.   {
  167.     /* Sun is special */
  168.     if (p == 0)
  169.     {
  170.       MakeSunList();
  171.     }
  172.     else
  173.     {
  174.       MakePlanetList (p);
  175.     }
  176.   }
  177.  
  178.   /* Make orbit lists */
  179.   MakeOrbitLists();
  180. }
  181.  
  182. void MakePlanetList (int p)
  183. /*
  184.  *  Make planet lists for planet p
  185.  */
  186. {
  187.   /* We make three different versions of the planet for display at various
  188.     distances */
  189.   if (glIsList (planet[p].list20)) glDeleteLists (planet[p].list20, 1);
  190.   planet[p].list20 = glGenLists (1);
  191.  
  192.   glNewList (planet[p].list20, GL_COMPILE);
  193.   maxtdiff = 0.47;
  194.   Sphere (planet[p].radius, stacks0, slices0);
  195.   glEndList();
  196.  
  197.   if (glIsList (planet[p].list80)) glDeleteLists (planet[p].list80, 1);
  198.   planet[p].list80 = glGenLists (1);
  199.  
  200.   glNewList (planet[p].list80, GL_COMPILE);
  201.   maxtdiff = 0.609384;
  202.   Sphere (planet[p].radius, stacks1, slices1);
  203.   glEndList();
  204.  
  205.   if (glIsList (planet[p].list320)) glDeleteLists (planet[p].list320, 1);
  206.   planet[p].list320 = glGenLists (1);
  207.  
  208.   glNewList (planet[p].list320, GL_COMPILE);
  209.   maxtdiff = 0.414069;
  210.   Sphere (planet[p].radius, stacks2, slices2);
  211.   glEndList();
  212. }
  213.  
  214. void MakeSunList()
  215. /*
  216.  *  Make Sol's display list
  217.  */
  218. {
  219.   if (glIsList (planet[0].list20)) glDeleteLists (planet[0].list20, 1);
  220.   planet[0].list20 = glGenLists (1);
  221.  
  222.   glNewList (planet[0].list20, GL_COMPILE);
  223.   glDisable (GL_LIGHTING);
  224.   glDisable (GL_TEXTURE_2D);
  225.   glColor3f (0.8, 0.8, 0.6);
  226.   Sphere (planet[0].radius, stacks0, slices0);
  227.   glEnable (GL_TEXTURE_2D);
  228.   glEnable (GL_LIGHTING);
  229.   glEndList();
  230.  
  231.   if (glIsList (planet[0].list80)) glDeleteLists (planet[0].list80, 1);
  232.   planet[0].list80 = glGenLists (1);
  233.  
  234.   glNewList (planet[0].list80, GL_COMPILE);
  235.   glDisable (GL_LIGHTING);
  236.   glDisable (GL_TEXTURE_2D);
  237.   glColor3f (0.8, 0.8, 0.6);
  238.   Sphere (planet[0].radius, stacks1, slices1);
  239.   glEnable (GL_TEXTURE_2D);
  240.   glEnable (GL_LIGHTING);
  241.   glEndList();
  242.  
  243.   if (glIsList (planet[0].list320)) glDeleteLists (planet[0].list320, 1);
  244.   planet[0].list320 = glGenLists (1);
  245.  
  246.   glNewList (planet[0].list320, GL_COMPILE);
  247.   glDisable (GL_LIGHTING);
  248.   glDisable (GL_TEXTURE_2D);
  249.   glColor3f (0.8, 0.8, 0.6);
  250.   Sphere (planet[0].radius, stacks2, slices2);
  251.   glEnable (GL_TEXTURE_2D);
  252.   glEnable (GL_LIGHTING);
  253.   glEndList();
  254. }
  255.  
  256. void ReadPlanetTexture (int p)
  257. /*
  258.  *  Read in the planet's texture
  259.  */
  260. {
  261.   FILE *fd;
  262.   int x, y, c, i;
  263.   char fn[64];
  264.  
  265.   /* Sun is special */
  266.   if (p == 0)
  267.   {
  268.     planet[p].color[0] = planet[p].color[1] = planet[p].color[2] = 1.0;
  269.     return;
  270.   }
  271.  
  272.   /* Zero planet average color */
  273.   planet[p].color[0] = planet[p].color[1] = planet[p].color[2] = 0.0;
  274.  
  275.   /* Get id for this texture */
  276.   if (planet[p].texid == (-1)) glGenTextures (1, &planet[p].texid);
  277.   glBindTexture (GL_TEXTURE_2D, planet[p].texid);
  278.  
  279.   glPixelStorei (GL_UNPACK_ALIGNMENT, 1);
  280.  
  281.   /* Put up a progress message */
  282.   Mprint ("Reading %s", planet[p].texfname);
  283.   Log ("ReadPlanetTexture: Reading texture file %s", planet[p].texfname);
  284.   DrawSplash();
  285.  
  286.   /* Open file */
  287.   sprintf (fn, "maps/%s", planet[p].texfname);
  288.   if (NULL == (fd = fopen (fn, "rb")))
  289.   {
  290.     Log ("ReadPlanetTexture: Can't open %s", planet[p].texfname);
  291.     FinishSound();
  292.     CloseLog();
  293.     exit (0);
  294.   }
  295.  
  296.   /* Read past PPM header */
  297.   while (10 != fgetc(fd));
  298.   while (10 != fgetc(fd));
  299.   while (10 != fgetc(fd));
  300.  
  301.   /* Read in the color data */
  302.   for (y=0; y<256; y++)
  303.   {
  304.     for (x=0; x<256; x++)
  305.     {
  306.       for (i=0; i<3; i++)
  307.       {
  308.         c = fgetc (fd);
  309.         if ( (c < 0) || (c > 255) )
  310.         {
  311.           Log ("ReadPlanetTexture: Error reading texture file %s", planet[p].texfname);
  312.           Log ("ReadPlanetTexture: x,y,i,c; %d %d %d %d", x, y, i, c);
  313.           FinishSound();
  314.           CloseLog();
  315.           exit (0);
  316.         }
  317.  
  318.         planet[p].tex[255-y][x][i] = 0xff & c;
  319.         planet[p].color[i] += (float) c;
  320.       }
  321.     }
  322.   }
  323.  
  324.   /* Compute average color */
  325.   for (i=0; i<3; i++) planet[p].color[i] /= (256.0 * 256.0 * 256.0);
  326.  
  327.   /* Set the texture */
  328.   glTexImage2D (GL_TEXTURE_2D, 0, 3, 256, 256, 0, GL_RGB, GL_UNSIGNED_BYTE, planet[p].tex);
  329.   glTexParameterf (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
  330.   glTexParameterf (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
  331.   glTexParameterf (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
  332.   glTexParameterf (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
  333.   glTexEnvf (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
  334.  
  335.   fclose (fd);
  336. }
  337.  
  338. void InitPlanets()
  339. /*
  340.  *  All sorts of planet initialization
  341.  */
  342. {
  343.   int p;
  344.  
  345.   for (p=0; p<NPLANETS; p++)
  346.   {
  347.     planet[p].custom = 1;
  348.     planet[p].texid = (-1);
  349.     planet[p].orbitlist = (-1);
  350.   }
  351.  
  352.   /* Randomize theta for each planet */
  353.   RandomPlanets();
  354.  
  355.   /* Reset planets */
  356.   ResetPlanets();
  357. }
  358.  
  359. void ResetPlanets()
  360. /*
  361.  *  Set planets back to the way they should be at start
  362.  */
  363. {
  364.   int p;
  365.  
  366.   p = 0;
  367.  
  368.   Log ("ResetPlanets: resetting planets");
  369.  
  370.   strcpy (planet[p].name, "Sol");
  371.   strcpy (planet[p].texfname, "sol.ppm");
  372.   planet[p].radius = 696000.000000 / KM_TO_UNITS1;
  373.   planet[p].dist = 0.000000 / KM_TO_UNITS2;
  374.   planet[p].is_moon = 0;
  375.   planet[p].primary = 0;
  376.   planet[p].oblicity = 0.0;
  377.   planet[p].angvel = 0.0;
  378.   p++;
  379.  
  380.   strcpy (planet[p].name, "Mercury");
  381.   strcpy (planet[p].texfname, "mercury.ppm");
  382.   planet[p].radius = 2440.000000 / KM_TO_UNITS1;
  383.   planet[p].dist = (realdistances ? 50.79 : 05.7900002) / KM_TO_UNITS2;
  384.   planet[p].is_moon = 0;
  385.   planet[p].primary = 0;
  386.   planet[p].angvel = 0.004166 / 87.969;
  387.   p++;
  388.  
  389.   strcpy (planet[p].name, "Venus");
  390.   strcpy (planet[p].texfname, "venus.ppm");
  391.   planet[p].radius = 6052.000000 / KM_TO_UNITS1;
  392.   planet[p].dist = (realdistances ? 108.2 : 10.8199997) / KM_TO_UNITS2;
  393.   planet[p].is_moon = 0;
  394.   planet[p].primary = 0;
  395.   planet[p].oblicity = 177.3;
  396.   planet[p].angvel = 0.004166 / 224.7;
  397.   p++;
  398.  
  399.   strcpy (planet[p].name, "Earth");
  400.   strcpy (planet[p].texfname, "earth.ppm");
  401.   planet[p].radius = 6371.000000 / KM_TO_UNITS1;
  402.   planet[p].dist = (realdistances ? 149.6 : 14.9600006) / KM_TO_UNITS2;
  403.   planet[p].is_moon = 0;
  404.   planet[p].primary = 0;
  405.   planet[p].oblicity = 23.45;
  406.   planet[p].angvel = 0.004166 / 365.256;
  407.   p++;
  408.  
  409.   strcpy (planet[p].name, "Moon");
  410.   strcpy (planet[p].texfname, "moon.ppm");
  411.   planet[p].radius = 1737.500000 / KM_TO_UNITS1;
  412.   planet[p].dist = 0.384400 / KM_TO_UNITS2;
  413.   planet[p].is_moon = 1;
  414.   planet[p].primary = 3;
  415.   planet[p].oblicity = 0.0;
  416.   planet[p].angvel = 0.004166 / 27.3;
  417.   p++;
  418.  
  419.   strcpy (planet[p].name, "Mars");
  420.   strcpy (planet[p].texfname, "mars.ppm");
  421.   planet[p].radius = 3390.000000 / KM_TO_UNITS1;
  422.   planet[p].dist = (realdistances ? 227.9 : 22.7899994) / KM_TO_UNITS2;
  423.   planet[p].is_moon = 0;
  424.   planet[p].primary = 0;
  425.   planet[p].oblicity = 25.19;
  426.   planet[p].angvel = 0.004166 / 686.98;
  427.   p++;
  428.  
  429.   strcpy (planet[p].name, "Phobos");
  430.   strcpy (planet[p].texfname, "phobos.ppm");
  431.   planet[p].radius = 13.000000 / KM_TO_UNITS1;
  432.   planet[p].dist = 0.009380 / KM_TO_UNITS2;
  433.   planet[p].is_moon = 1;
  434.   planet[p].primary = 5;
  435.   planet[p].oblicity = 0.0;
  436.   planet[p].angvel = 0.004166 / 0.319;
  437.   p++;
  438.  
  439.   strcpy (planet[p].name, "Deimos");
  440.   strcpy (planet[p].texfname, "deimos.ppm");
  441.   planet[p].radius = 8.000000 / KM_TO_UNITS1;
  442.   planet[p].dist = 0.022340 / KM_TO_UNITS2;
  443.   planet[p].is_moon = 1;
  444.   planet[p].primary = 5;
  445.   planet[p].oblicity = 0.0;
  446.   planet[p].angvel = 0.004166 / 1.262;
  447.   p++;
  448.  
  449.   strcpy (planet[p].name, "Jupiter");
  450.   strcpy (planet[p].texfname, "jupiter.ppm");
  451.   planet[p].radius = 69911.000000 / KM_TO_UNITS1;
  452.   /* planet[p].dist = 77.8400024 / KM_TO_UNITS2; */
  453.   planet[p].dist = (realdistances ? 778.4 : 50.0) / KM_TO_UNITS2;
  454.   planet[p].is_moon = 0;
  455.   planet[p].primary = 0;
  456.   planet[p].oblicity = 3.12;
  457.   planet[p].angvel = 0.004166 / 4332.0;
  458.   p++;
  459.  
  460.   strcpy (planet[p].name, "Io");
  461.   strcpy (planet[p].texfname, "io.ppm");
  462.   planet[p].radius = 1821.000000 / KM_TO_UNITS1;
  463.   planet[p].dist = 0.421000 / KM_TO_UNITS2;
  464.   planet[p].is_moon = 1;
  465.   planet[p].primary = 8;
  466.   planet[p].oblicity = 0.0;
  467.   planet[p].angvel = 0.004166 / 1.769;
  468.   p++;
  469.  
  470.   strcpy (planet[p].name, "Europa");
  471.   strcpy (planet[p].texfname, "europa.ppm");
  472.   planet[p].radius = 1565.000000 / KM_TO_UNITS1;
  473.   planet[p].dist = 0.671000 / KM_TO_UNITS2;
  474.   planet[p].is_moon = 1;
  475.   planet[p].primary = 8;
  476.   planet[p].oblicity = 0.0;
  477.   planet[p].angvel = 0.004166 / 3.552;
  478.   p++;
  479.  
  480.   strcpy (planet[p].name, "Ganymede");
  481.   strcpy (planet[p].texfname, "ganymede.ppm");
  482.   planet[p].radius = 2634.000000 / KM_TO_UNITS1;
  483.   planet[p].dist = 1.070000 / KM_TO_UNITS2;
  484.   planet[p].is_moon = 1;
  485.   planet[p].primary = 8;
  486.   planet[p].oblicity = 0.0;
  487.   planet[p].angvel = 0.004166 / 7.155;
  488.   p++;
  489.  
  490.   strcpy (planet[p].name, "Callisto");
  491.   strcpy (planet[p].texfname, "callisto.ppm");
  492.   planet[p].radius = 2403.000000 / KM_TO_UNITS1;
  493.   planet[p].dist = 1.883000 / KM_TO_UNITS2;
  494.   planet[p].is_moon = 1;
  495.   planet[p].primary = 8;
  496.   planet[p].oblicity = 0.0;
  497.   planet[p].angvel = 0.004166 / 16.69;
  498.   p++;
  499.  
  500.   strcpy (planet[p].name, "Saturn");
  501.   strcpy (planet[p].texfname, "saturn.ppm");
  502.   planet[p].radius = 58232.000000 / KM_TO_UNITS1;
  503.   /* planet[p].dist = 142.7000000 / KM_TO_UNITS2; */
  504.   planet[p].dist = (realdistances ? 1427.0 : 75.0) / KM_TO_UNITS2;
  505.   planet[p].is_moon = 0;
  506.   planet[p].primary = 0;
  507.   planet[p].oblicity = 26.73;
  508.   planet[p].angvel = 0.004166 / 10759.0;
  509.   p++;
  510.  
  511.   strcpy (planet[p].name, "Mimas");
  512.   strcpy (planet[p].texfname, "mimas.ppm");
  513.   planet[p].radius = 198.800003 / KM_TO_UNITS1;
  514.   planet[p].dist = 0.185000 / KM_TO_UNITS2;
  515.   planet[p].is_moon = 1;
  516.   planet[p].primary = 13;
  517.   planet[p].oblicity = 0.0;
  518.   planet[p].angvel = 0.004166 / 0.942;
  519.   p++;
  520.  
  521.   strcpy (planet[p].name, "Enceladus");
  522.   strcpy (planet[p].texfname, "enceladus.ppm");
  523.   planet[p].radius = 249.100006 / KM_TO_UNITS1;
  524.   planet[p].dist = 0.238000 / KM_TO_UNITS2;
  525.   planet[p].is_moon = 1;
  526.   planet[p].primary = 13;
  527.   planet[p].oblicity = 0.0;
  528.   planet[p].angvel = 0.004166 / 1.37;
  529.   p++;
  530.  
  531.   strcpy (planet[p].name, "Tethys");
  532.   strcpy (planet[p].texfname, "tethys.ppm");
  533.   planet[p].radius = 529.900024 / KM_TO_UNITS1;
  534.   planet[p].dist = 0.294000 / KM_TO_UNITS2;
  535.   planet[p].is_moon = 1;
  536.   planet[p].primary = 13;
  537.   planet[p].oblicity = 0.0;
  538.   planet[p].angvel = 0.004166 / 1.888;
  539.   p++;
  540.  
  541.   strcpy (planet[p].name, "Dione");
  542.   strcpy (planet[p].texfname, "dione.ppm");
  543.   planet[p].radius = 560.000000 / KM_TO_UNITS1;
  544.   planet[p].dist = 0.377000 / KM_TO_UNITS2;
  545.   planet[p].is_moon = 1;
  546.   planet[p].primary = 13;
  547.   planet[p].oblicity = 0.0;
  548.   planet[p].angvel = 0.004166 / 2.737;
  549.   p++;
  550.  
  551.   strcpy (planet[p].name, "Rhea");
  552.   strcpy (planet[p].texfname, "rhea.ppm");
  553.   planet[p].radius = 764.000000 / KM_TO_UNITS1;
  554.   planet[p].dist = 0.527000 / KM_TO_UNITS2;
  555.   planet[p].is_moon = 1;
  556.   planet[p].primary = 13;
  557.   planet[p].oblicity = 0.0;
  558.   planet[p].angvel = 0.004166 / 4.518;
  559.   p++;
  560.  
  561.   strcpy (planet[p].name, "Titan");
  562.   strcpy (planet[p].texfname, "titan.ppm");
  563.   planet[p].radius = 2575.000000 / KM_TO_UNITS1;
  564.   planet[p].dist = 1.221000 / KM_TO_UNITS2;
  565.   planet[p].is_moon = 1;
  566.   planet[p].primary = 13;
  567.   planet[p].oblicity = 0.0;
  568.   planet[p].angvel = 0.004166 / 15.9;
  569.   p++;
  570.  
  571.   strcpy (planet[p].name, "Iapetus");
  572.   strcpy (planet[p].texfname, "iapetus.ppm");
  573.   planet[p].radius = 718.000000 / KM_TO_UNITS1;
  574.   planet[p].dist = 3.561000 / KM_TO_UNITS2;
  575.   planet[p].is_moon = 1;
  576.   planet[p].primary = 13;
  577.   planet[p].oblicity = 0.0;
  578.   planet[p].angvel = 0.004166 / 79.33;
  579.   p++;
  580.  
  581.   strcpy (planet[p].name, "Uranus");
  582.   strcpy (planet[p].texfname, "uranus.ppm");
  583.   planet[p].radius = 25362.000000 / KM_TO_UNITS1;
  584.   /* planet[p].dist = 287.1000000 / KM_TO_UNITS2; */
  585.   planet[p].dist = (realdistances ? 2871.0 : 100.0) / KM_TO_UNITS2;
  586.   planet[p].is_moon = 0;
  587.   planet[p].primary = 0;
  588.   planet[p].oblicity = 97.86;
  589.   planet[p].angvel = 0.004166 / 30685.0;
  590.   p++;
  591.  
  592.   strcpy (planet[p].name, "Miranda");
  593.   strcpy (planet[p].texfname, "miranda.ppm");
  594.   planet[p].radius = 235.000000 / KM_TO_UNITS1;
  595.   planet[p].dist = 0.130000 / KM_TO_UNITS2;
  596.   planet[p].is_moon = 1;
  597.   planet[p].primary = 21;
  598.   planet[p].oblicity = 0.0;
  599.   planet[p].angvel = 0.004166 / 1.413;
  600.   p++;
  601.  
  602.   strcpy (planet[p].name, "Ariel");
  603.   strcpy (planet[p].texfname, "ariel.ppm");
  604.   planet[p].radius = 580.000000 / KM_TO_UNITS1;
  605.   planet[p].dist = 0.191000 / KM_TO_UNITS2;
  606.   planet[p].is_moon = 1;
  607.   planet[p].primary = 21;
  608.   planet[p].oblicity = 0.0;
  609.   planet[p].angvel = 0.004166 / 2.52;
  610.   p++;
  611.  
  612.   strcpy (planet[p].name, "Umbriel");
  613.   strcpy (planet[p].texfname, "umbriel.ppm");
  614.   planet[p].radius = 585.000000 / KM_TO_UNITS1;
  615.   planet[p].dist = 0.266000 / KM_TO_UNITS2;
  616.   planet[p].is_moon = 1;
  617.   planet[p].primary = 21;
  618.   planet[p].oblicity = 0.0;
  619.   planet[p].angvel = 0.004166 / 4.144;
  620.   p++;
  621.  
  622.   strcpy (planet[p].name, "Titania");
  623.   strcpy (planet[p].texfname, "titania.ppm");
  624.   planet[p].radius = 789.000000 / KM_TO_UNITS1;
  625.   planet[p].dist = 0.436000 / KM_TO_UNITS2;
  626.   planet[p].is_moon = 1;
  627.   planet[p].primary = 21;
  628.   planet[p].oblicity = 0.0;
  629.   planet[p].angvel = 0.004166 / 8.706;
  630.   p++;
  631.  
  632.   strcpy (planet[p].name, "Oberon");
  633.   strcpy (planet[p].texfname, "oberon.ppm");
  634.   planet[p].radius = 761.000000 / KM_TO_UNITS1;
  635.   planet[p].dist = 0.583000 / KM_TO_UNITS2;
  636.   planet[p].is_moon = 1;
  637.   planet[p].primary = 21;
  638.   planet[p].oblicity = 0.0;
  639.   planet[p].angvel = 0.004166 / 13.463;
  640.   p++;
  641.  
  642.   strcpy (planet[p].name, "Neptune");
  643.   strcpy (planet[p].texfname, "neptune.ppm");
  644.   planet[p].radius = 24766.000000 / KM_TO_UNITS1;
  645.   /* planet[p].dist = 449.8000000 / KM_TO_UNITS2; */
  646.   planet[p].dist = (realdistances ? 4498.0 : 125.0) / KM_TO_UNITS2;
  647.   planet[p].is_moon = 0;
  648.   planet[p].primary = 0;
  649.   planet[p].oblicity = 29.56;
  650.   planet[p].angvel = 0.004166 / 60189.0;
  651.   p++;
  652.  
  653.   strcpy (planet[p].name, "Triton");
  654.   strcpy (planet[p].texfname, "triton.ppm");
  655.   planet[p].radius = 1352.599976 / KM_TO_UNITS1;
  656.   planet[p].dist = 0.355000 / KM_TO_UNITS2;
  657.   planet[p].is_moon = 1;
  658.   planet[p].primary = 27;
  659.   planet[p].oblicity = 0.0;
  660.   planet[p].angvel = 0.004166 / -5.877;
  661.   p++;
  662.  
  663.   strcpy (planet[p].name, "Proteus");
  664.   strcpy (planet[p].texfname, "proteus.ppm");
  665.   planet[p].radius = 218.000000 / KM_TO_UNITS1;
  666.   planet[p].dist = 0.118000 / KM_TO_UNITS2;
  667.   planet[p].is_moon = 1;
  668.   planet[p].primary = 27;
  669.   planet[p].oblicity = 0.0;
  670.   planet[p].angvel = 0.004166 / 1.122;
  671.   p++;
  672.  
  673.   strcpy (planet[p].name, "Pluto");
  674.   strcpy (planet[p].texfname, "pluto.ppm");
  675.   planet[p].radius = 1137.000000 / KM_TO_UNITS1;
  676.   /* planet[p].dist = 590.6000000 / KM_TO_UNITS2; */
  677.   planet[p].dist = (realdistances ? 5906.0 : 150.0) / KM_TO_UNITS2;
  678.   planet[p].is_moon = 0;
  679.   planet[p].primary = 0;
  680.   planet[p].oblicity = 122.0;
  681.   planet[p].angvel = 0.004166 / 90465.0;
  682.   p++;
  683.  
  684.   strcpy (planet[p].name, "Charon");
  685.   strcpy (planet[p].texfname, "charon.ppm");
  686.   planet[p].radius = 586.000000 / KM_TO_UNITS1;
  687.   planet[p].dist = 0.019000 / KM_TO_UNITS2;
  688.   planet[p].is_moon = 1;
  689.   planet[p].primary = 30;
  690.   planet[p].oblicity = 0.0;
  691.   planet[p].angvel = 0.004166 / 6.387;
  692.   p++;
  693.  
  694.   /* Randomize planet positions */
  695.   PositionPlanets();
  696.  
  697.   /* Read textures, etc */
  698.   for (p=0; p<NPLANETS; p++)
  699.   {
  700.     if (planet[p].custom)
  701.     {
  702.       ReadPlanetTexture (p);
  703.       planet[p].custom = 0;
  704.     }
  705.  
  706.     planet[p].radius2 = planet[p].radius * planet[p].radius;
  707.     planet[p].hidden = 0;
  708.  
  709.     /* Set planet's mass */
  710.     planet[p].mass = planet[p].radius * planet[p].radius * planet[p].radius;
  711.   }
  712.  
  713.   /* Define planet display lists */
  714.   MakePlanetLists();
  715. }
  716.  
  717. void RandomPlanets()
  718. /*
  719.  *  Randomly set solar angle for each planet
  720.  */
  721. {
  722.   int p;
  723.  
  724.   Log ("RandomPlanets: Randomizing planets");
  725.  
  726.   for (p=0; p<NPLANETS; p++)
  727.   {
  728.     planet[p].theta = 2.0 * rnd (6.28);
  729.   }
  730. }
  731.  
  732. void PositionPlanets()
  733. /*
  734.  *  Turn planet angles into Cartesian coordinates
  735.  */
  736. {
  737.   int p, pr;
  738.   double th, v[3], v1[3];
  739.  
  740.   /* Position the planets */
  741.   for (p=0; p<NPLANETS; p++)
  742.   {
  743.     th = planet[p].theta;
  744.  
  745.     planet[p].pos[0] = planet[p].dist * sin (th);
  746.     planet[p].pos[1] = planet[p].dist * cos (th);
  747.     planet[p].pos[2] = 0.0;
  748.  
  749.     /* If moon, compute absolute position based on primary's
  750.      position and oblicity */
  751.     if (planet[p].is_moon)
  752.     {
  753.       pr = planet[p].primary;
  754.       th = -planet[pr].oblicity * 3.1415926535 / 180.0;
  755.       v[0] = 1.0;
  756.       v[1] = 0.0;
  757.       v[2] = 0.0;
  758.       RotateAbout (v1, planet[p].pos, v, th);
  759.       Vset (planet[p].pos, v1);
  760.       Vadd (planet[p].pos, planet[p].pos, planet[pr].pos);
  761.     }
  762.   }
  763. }
  764.  
  765. int InsidePlanet (double *v)
  766. /*
  767.  *  Check if v is inside a planet.  If yes, return planet
  768.  *  index, else -1
  769.  */
  770. {
  771.   int p;
  772.   double v1[3], r2;
  773.  
  774.   for (p=0; p<NPLANETS; p++)
  775.   {
  776.     if (!planet[p].hidden)
  777.     {
  778.       Vsub (v1, v, planet[p].pos);
  779.       r2 = Mag2 (v1);
  780.  
  781.       /* Inside? */
  782.       if (r2 < planet[p].radius2)
  783.       {
  784.         /* Yep */
  785.         return (p);
  786.       }
  787.     }
  788.   }
  789.  
  790.   /* Nope */
  791.   return (-1);
  792. }
  793.  
  794. void ShowPlanetNames()
  795. {
  796.   int p;
  797.   unsigned char v;
  798.   double v1[3]; 
  799.   char buf[128];
  800.  
  801.   for (p=0; p<NPLANETS; p++)
  802.   {
  803.     if (!planet[p].hidden)
  804.     {
  805.       if (planet[p].is_moon)
  806.       glColor3f (0.0, 0.8, 0.8);
  807.       else
  808.       glColor3f (0.0, 0.0, 0.8);
  809.  
  810.       Vsub (v1, planet[p].pos, player.pos);
  811.       glRasterPos3dv (v1);
  812.       glGetBooleanv (GL_CURRENT_RASTER_POSITION_VALID, &v);
  813.       if (v)
  814.       {
  815.         if (!planet[p].is_moon)
  816.         {
  817.           if (planet[p].absrange2 < 100.0*planet[p].radius*planet[p].radius) 
  818.           {
  819.             sprintf (buf, "%s:%.0lf", planet[p].name, 
  820.             KM_TO_UNITS1*(sqrt(planet[p].absrange2)-planet[p].radius)); 
  821.           }
  822.           else 
  823.           {
  824.             strcpy (buf, planet[p].name); 
  825.           }
  826.           Print (GLUT_BITMAP_HELVETICA_10, buf);
  827.         }
  828.         else
  829.         {
  830.           if (planet[p].range2 < (2000.0 * 2000.0))
  831.           {
  832.             if (planet[p].absrange2 < 100.0*planet[p].radius*planet[p].radius) 
  833.             {
  834.               sprintf (buf, "%s:%.0lf", planet[p].name, 
  835.               KM_TO_UNITS1*(sqrt(planet[p].absrange2)-planet[p].radius)); 
  836.             }
  837.             else 
  838.             {
  839.               strcpy (buf, planet[p].name); 
  840.             }
  841.             Print (GLUT_BITMAP_HELVETICA_10, buf);
  842.           }
  843.         }
  844.       }
  845.     }
  846.   }
  847. }
  848.  
  849. void Sphere (double r, int slices, int sectors)
  850. {
  851.   GLUquadricObj *obj;
  852.  
  853.   obj = gluNewQuadric();
  854.   
  855.   gluQuadricDrawStyle (obj, GLU_FILL);
  856.   gluQuadricNormals (obj, GLU_SMOOTH);
  857.   gluQuadricTexture (obj, GL_TRUE);
  858.   gluSphere (obj, (float)r, sectors, slices);
  859. }
  860.  
  861. int FindPlanetByName (char *c)
  862. /*
  863.  *  Find planet given name, else -1
  864.  */
  865. {
  866.   int p;
  867.  
  868.   for (p=0; p<NPLANETS; p++)
  869.   {
  870.     if (!strcasecmp (c, planet[p].name)) return (p);
  871.   }
  872.  
  873.   return (-1);
  874. }
  875.  
  876. void MakeOrbitLists()
  877. /*
  878.  *  Construct display lists for orbits
  879.  */
  880. {
  881.   int p;
  882.   double th, d, s, c;
  883.  
  884.   d = 360.0 / ((double) ORBIT_SECTORS);
  885.  
  886.   /* Loop through planets */
  887.   for (p=1; p<NPLANETS; p++)
  888.   {
  889.     /* Delete old list */
  890.     if (glIsList (planet[p].orbitlist)) glDeleteLists (planet[p].orbitlist, 1);
  891.  
  892.     /* Make new list */
  893.     planet[p].orbitlist = glGenLists (1);
  894.     glNewList (planet[p].orbitlist, GL_COMPILE);
  895.  
  896.     glBegin (GL_LINE_LOOP);
  897.  
  898.     /* Set color */
  899.     if (planet[p].is_moon)
  900.     {
  901.       glColor3f (0.0, 0.8, 0.8);
  902.     }
  903.     else
  904.     {
  905.       glColor3f (0.0, 0.0, 1.0);
  906.     }
  907.  
  908.     /* Loop through circle */
  909.     for (th=0.0; th<360.0; th+=d)
  910.     {
  911.       s = sin (th*3.1415926535/180.0);
  912.       c = cos (th*3.1415926535/180.0);
  913.  
  914.       glVertex3d (planet[p].dist*s, planet[p].dist*c, 0.0);
  915.     }
  916.  
  917.     glEnd();
  918.     glEndList();
  919.   }
  920. }
  921.  
  922. void DrawOrbits()
  923. /*
  924.  *  Draw orbital paths
  925.  */
  926. {
  927.   int p;
  928.   double v[3];
  929.  
  930.   glDisable (GL_TEXTURE_2D);
  931.   glDisable (GL_LIGHTING);
  932.  
  933.   glPushMatrix();
  934.   Vsub (v, planet[0].pos, player.pos);
  935.   glTranslated (v[0], v[1], v[2]);
  936.  
  937.   for (p=1; p<NPLANETS; p++)
  938.   {
  939.     if (!planet[p].hidden)
  940.     {
  941.       if (planet[p].is_moon)
  942.       {
  943.         if (planet[planet[p].primary].range2 > 200.0*200.0) continue;
  944.  
  945.         glPushMatrix();
  946.         Vsub (v, player.pos, planet[0].pos);
  947.         glTranslated (v[0], v[1], v[2]);
  948.  
  949.         Vsub (v, planet[planet[p].primary].pos, player.pos);
  950.         glTranslated (v[0], v[1], v[2]);
  951.  
  952.         glRotated (planet[planet[p].primary].oblicity, 1.0, 0.0, 0.0);
  953.       }
  954.       glCallList (planet[p].orbitlist);
  955.       if (planet[p].is_moon) glPopMatrix();
  956.     }
  957.   }
  958.  
  959.   glPopMatrix();
  960. }
  961.  
  962. void MovePlanets()
  963. /*
  964.  *  Move planets in their orbits
  965.  */
  966. {
  967.   int p;
  968.  
  969.   for (p=1; p<NPLANETS; p++)
  970.   {
  971.     planet[p].theta -= planet[p].angvel * deltaT * compression 
  972.     * 3.1415926535 / 180.0; 
  973.     if (planet[p].theta < 0.0) planet[p].theta += 2.0 * 3.1415926535; 
  974.   }
  975.  
  976.   PositionPlanets();
  977. }
  978.